<!DOCTYPE html>
<html>

<head>
    <title>Fraunhofer FOKUS - HEVC Tiled MSE Player Minimal Demo</title>
    <script type="text/javascript" src="libs/iso_boxer.min.js"></script>
    <script type="text/javascript" src="libs/hevc_merger.js"></script>
</head>

<body>
    <video autoplay style="width: 100%; height: auto;" loop></video>

    <script type="text/javascript">
        // Configuration Player
        let video = document.querySelector('video')
        let grid_size = [3, 3]
        let current_matrix = [0, 1, 0, 1, 2, 1, 0, 1, 0]
        /*
            PLEASE NOTE, the tile positon is as following:
            [0, 1, 2
            ,3, 4, 5
            ,6, 7, 8]

            In case of non-square grid (2 rows, 4 columns):
            [0, 1, 2, 3
            ,4, 5, 6, 7]
        */

        // Configuration Media
        let media = {
            "content_url_scheme": "media/radbul/radbul_3x3_dash_%bitrate%/radbul-3840x1920-3x3-%bitrate%_dash_track%tile%_%segment%.m4s",
            "dash_init": "media/radbul/radbul_3x3_dash_%bitrate%/dash_set1_init.mp4",
            "update_dash_init": true,
            "nb_segments": 102,
            "base_track": 1,
            "bitrates": [1000, 3000, 10000],
            "tracks": [2, 3, 4, 5, 6, 7, 8, 9, 10]
        }

        let current_segment = 'init'
        let source_buffer, media_source = new MediaSource(), merger = new HEVCMerger()

        let _setPlayer = () => {
            video.src = window.URL.createObjectURL(media_source)

            media_source.addEventListener('sourceopen', e => {
                source_buffer = media_source.addSourceBuffer('video/mp4; codecs="hev1.1.6.L186.80"')

                console.log("Source is open")

                source_buffer.addEventListener('updateend', () => {
                    _append()
                })

                _append()
            }, false)
        }

        let _append = () => {
            if (current_segment === "init" && (current_segment = 1)) {
                _loadInit().then(arrayBuffer => source_buffer.appendBuffer(arrayBuffer))
                return true
            }
            else if (current_segment <= media.nb_segments) {
                _loadSegment().then(arrayBuffer => source_buffer.appendBuffer(arrayBuffer))
                return true
            }
            else
                return false
        }

        let _loadSegment = () => {
            return new Promise((resolve, reject) => {
                let segment_number = current_segment
                let buffers = []
                let promises = []
                let start = Date.now()
                let scheme = media.content_url_scheme.replace('%segment%', segment_number)

                for (let i = 0; i < grid_size[0] * grid_size[1]; i++)
                    promises.push(fetch(scheme.replace(new RegExp('%bitrate%', 'g'), media.bitrates[current_matrix[i]]).replace('%tile%', media.tracks[i])).then(r => r.arrayBuffer())
                        .then(arrayBuffer => buffers[i] = arrayBuffer))

                promises.push(fetch(scheme.replace(new RegExp('%bitrate%', 'g'), media.bitrates[0]).replace('%tile%', media.base_track)).then(r => r.arrayBuffer())
                    .then(arrayBuffer => buffers[grid_size[0] * grid_size[1]] = arrayBuffer))

                Promise.all(promises).then(r => {
                    try {
                        let step = Date.now()
                        //download = step - start
                        let merged_content = merger.merge(buffers, segment_number)
                        //Date.now() - step
                        current_segment += 1
                        resolve(merged_content)
                    }
                    catch (e) {
                        console.error(e)
                    }
                })
            })
        }

        let _loadInit = () => {
            // load dash init
            if (media.update_dash_init)
                return fetch(media.dash_init.replace(new RegExp('%bitrate%', 'g'), media.bitrates[0])).then(r => r.arrayBuffer()).then(arrayBuffer => merger.update(arrayBuffer))
            else
                return fetch(media.dash_init).then(r => r.arrayBuffer())
        }

        _setPlayer()
    </script>
</body>

</html>